<?php

namespace App\Http\Controllers\Home\Auth;

use App\Models\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Auth\Registrar;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use Illuminate\Cache\RateLimiter;

class AuthController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Registration & Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles the registration of new users, as well as the
    | authentication of existing users. By default, this controller uses
    | a simple trait to add these behaviors. Why don't you explore it?
    |
    */

    use AuthenticatesAndRegistersUsers, ThrottlesLogins;

    /**
     * Where to redirect users after login / registration.
     *
     * @var string
     */
    protected $redirectTo = '/';

    //是否验证失败多次后锁定
    protected $throttles = true;

    //用户登录的最多尝试次数
    protected $maxLoginAttempts = 3;

    //用户尝试失败后的锁定秒数
    protected $lockoutTime = 60;

    //注册/登录成功后的跳转地址
    protected $redirectPath = '/';

    //登录跳转地址
    protected $loginPath = 'auth/auth/login';

    //退出后的跳转地址
    protected $redirectAfterLogout = 'auth/auth/login';

    //视图文件夹
    protected $viewDir = 'home.auth';


    /**
     * Create a new authentication controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware($this->guestMiddleware(), ['except' => 'logout']);
    }

    /**
     * 显示登录页面
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function getLogin(){
        return view("home.auth.login");
    }

    /**
     * 处理登录请求
     */
    public function postLogin(Request $request)
    {
        //验证参数
        $valid_arg = array(
            'username' => 'required|max:20',
            'password' => 'required|min:6'
        );
        $this->validate($request,$valid_arg);

        //登录失败多次后锁定(登录失败过多.请等 '.$seconds.' 秒钟再尝试)
        if ($this->throttles && $this->hasTooManyLoginAttempts($request))
        {
            return $this->sendLockoutResponse($request);
        }

        //从请求获取所需的授权凭证（返回用户名和密码数组）
        $credentials = $this->getCredentials($request);

        //认证用户，认证成功后跳转
        if (Auth::attempt($credentials, $request->has('remember')))
        {
            return $this->handleUserWasAuthenticated($request);
        }

        //如果登录尝试失败，记录失败次数，超过最大登录次数将被锁定。
        if ($this->throttles)
        {
            $this->incrementLoginAttempts($request);
        }

        //认证失败后的跳转
        return redirect($this->loginPath)
            ->withInput($request->only('username', 'remember'))
            ->withErrors([
                'username' => '账号或密码错误！',
            ]);
    }

    /**
     * 退出登录
     *
     * @return \Illuminate\Http\Response
     */
    public function getLogout()
    {
        Auth::logout();
        return redirect($this->redirectAfterLogout);
    }

    /**
     * 显示注册表单
     *
     * @return \Illuminate\Http\Response
     */
    public function getRegister()
    {
        return view("home.auth.register");
    }

    /**
     * 处理注册的请求
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function postRegister(Request $request)
    {
        $validator = $this->validator($request->all());

        if ($validator->fails())
        {
            $this->throwValidationException($request, $validator);
        }

        Auth::login($this->create($request->all()));
        return redirect($this->redirectPath);
    }





    /**
     * Get a validator for an incoming registration request.
     * @param  array  $data
     * @return \Illuminate\Contracts\Validation\Validator
     */
    protected function validator(array $data)
    {
        return Validator::make($data, [
            'agree' => 'accepted',
            'username' => 'required|max:255',
            'email' => 'required|email|max:255|unique:users',
            'password' => 'required|min:6|confirmed',
        ]);
    }

    /**
     * Create a new user instance after a valid registration.
     * @param  array  $data
     * @return User
     */
    protected function create(array $data)
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => bcrypt($data['password']),
        ]);
    }

    /**
     * 确定是否登录失败多次
     * @param  \Illuminate\Http\Request  $request
     * @return bool
     */
    protected function hasTooManyLoginAttempts(Request $request)
    {
        return app(RateLimiter::class)->tooManyAttempts(
            $request->input('username').$request->ip(),
            $this->maxLoginAttempts(), $this->lockoutTime() / 60
        );
    }


    /**
     * 获取用户登录的最多尝试次数
     * @return int
     */
    protected function maxLoginAttempts()
    {
        return property_exists($this, 'maxLoginAttempts') ? $this->maxLoginAttempts : 5;
    }

    /**
     * 用户多次登录失败后的锁定秒数
     * @return int
     */
    protected function lockoutTime()
    {
        return property_exists($this, 'lockoutTime') ? $this->lockoutTime : 60;
    }

    /**
     * 用户被锁定后重定向
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\RedirectResponse
     */
    protected function sendLockoutResponse(Request $request)
    {
        $seconds = app(RateLimiter::class)->availableIn(
            $request->input('username').$request->ip()
        );
        return redirect($this->loginPath)
            ->withInput($request->only('username', 'remember'))
            ->withErrors([
                'username' => $this->getLockoutErrorMessage($seconds),
            ]);
    }

    /**
     * 获取登录失败后的锁定信息
     * @param  int  $seconds 秒数
     * @return string
     */
    protected function getLockoutErrorMessage($seconds)
    {
        return '登录失败过多.请等 '.$seconds.' 秒钟再尝试.';
    }

    /**
     * 从请求获取所需的授权凭证
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    protected function getCredentials(Request $request)
    {
        return $request->only('username', 'password');
    }

    /**
     * 用户通过身份验证后发送响应
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    protected function handleUserWasAuthenticated(Request $request)
    {
        if ($this->throttles)
        {
            $this->clearLoginAttempts($request);
        }
        if (method_exists($this, 'authenticated'))
        {
            return $this->authenticated($request, Auth::user());
        }
        Auth::user()->putPermissionToSession();
        return redirect()->intended($this->redirectPath);
    }

    /**
     * 清除用户凭证的登录锁定
     * @param  \Illuminate\Http\Request  $request
     * @return void
     */
    protected function clearLoginAttempts(Request $request)
    {
        app(RateLimiter::class)->clear(
            $request->input('username').$request->ip()
        );
    }

    /**
     * 增加用户登录失败次数
     * @param  \Illuminate\Http\Request  $request
     * @return int
     */
    protected function incrementLoginAttempts(Request $request)
    {
        app(RateLimiter::class)->hit(
            $request->input('username').$request->ip()
        );
    }

}
